package com.xzakota.minesweeper;

import com.xzakota.minesweeper.contant.ConstantPool;
import com.xzakota.minesweeper.log.XLogger;
import com.xzakota.minesweeper.model.PropertyListenable;
import com.xzakota.minesweeper.model.entity.RoomBean;
import com.xzakota.minesweeper.model.entity.UserBean;
import com.xzakota.minesweeper.msg.*;
import com.xzakota.minesweeper.ui.dialog.templae.MessageDialog;
import com.xzakota.minesweeper.util.JSONFileUtils;

import java.beans.PropertyChangeSupport;
import java.io.ObjectInputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 客户端 Socket 处理器
 *
 * @author Xzakota
 */
public class Client extends SocketHandler implements PropertyListenable {
    public static final Map<Integer, RoomBean> ROOM = new HashMap<>();
    private static final Client CLIENT = new Client();

    private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
    public UserBean currentUser = null;
    public int enterRoomNum = -1;

    public static void initSocket(String ip) {
        if (CLIENT.socketState == 1) {
            return;
        }
        try {
            String[] s = ip.split(":");
            CLIENT.socket = new Socket(s[0], Integer.parseInt(s[1]));
            XLogger.info("客户端 Socket 建立成功");
        } catch (Exception e) {
            CLIENT.socketState = 0;
            new MessageDialog("客户端 Socket 建立失败").showWindow();
        }
    }

    public static Client getClient() {
        return CLIENT;
    }

    public static synchronized void userRoom(GameAllRoomMsg msg) {
        ROOM.clear();
        ROOM.putAll(msg.getAllRoom());
        Client.getClient().firePropertyChange("ROOM", null, ROOM);
    }

    @Override
    public void run() {
        super.run();

        if (CLIENT.socketState != 1) {
            return;
        }

        String msg = "与服务端的 Socket 连接成功";
        XLogger.info(msg);
        new MessageDialog(msg).showWindow();

        try {
            while (!socket.isClosed() && !Thread.currentThread().isInterrupted()) {
                if (reader != null) {
                    while (reader.available() != 0) {
                        ObjectInputStream stream = new ObjectInputStream(reader);
                        Object msgObj = stream.readObject();

                        if (msgObj instanceof BaseMsg baseMsg) {
                            XLogger.info("客户端端收到信息: " + msgObj);
                            List<MsgHandler> handlerList = MsgHandlerFactory.createMsgHandlers(baseMsg);
                            if (handlerList != null) {
                                for (MsgHandler handler : new ArrayList<>(handlerList)) {
                                    handler.handle(baseMsg);
                                }
                            }
                        }
                    }
                } else {
                    XLogger.error("服务端 Socket 连接意外中断");
                    break;
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            socketState = 0;
            closeStream();
            XLogger.error("与服务端的 Socket 连接关闭");
        }
    }

    @Override
    public void close() {
        if (currentUser != null) {
            SignOutMsg signOutMsg = new SignOutMsg();
            signOutMsg.data = currentUser;
            JSONFileUtils.put(ConstantPool.SETTINGS_USER_HAS_SIGN_IN, false, true);
            sendMsg(signOutMsg);

            if (enterRoomNum == -1) {
                UserExitRoomMsg msg = new UserExitRoomMsg();
                msg.data = new Object[] {Client.getClient().currentUser, enterRoomNum};
                sendMsg(msg);
            }
        }

        socketState = 0;
        super.close();
    }

    @Override
    public PropertyChangeSupport getPropertyChangeSupport() {
        return pcs;
    }
}
